<template>
  <Select
    @on-change="handleChange"
    :value="initValue"
    :clearable="clearable"
    :loading="loading"
    :multiple="multiple"
    :placeholder="placeholder"
    filterable
    :disabled="disabled"
  >
    <Option
      v-for="item in options"
      :value="item[valueKey]"
      :key="item[valueKey]+Uuid.v1()"
    >{{ item[labelKey] }}</Option>
  </Select>
</template>
<script>
import { Select, Option } from "view-design";
import appService from "@/utils/appService";
import Uuid from "uuid";
import compare from "@/utils/compare";
export default {
  props: {
    api: {
      required: true,
      type: String
    },
    /** 查询数据时，往指定的vuex module推送loading状态 */
    namespace: {
      required: false,
      type: String
    },
    /** 查询参数 */
    queryParam: {
      type: Object
    },
    /** 是否需要参数才抓取数据 */
    needQueryParam: {
      type: Boolean,
      default: false,
      required: false
    },
    /** 展示字段的key */
    valueKey: {
      default: "id",
      type: String
    },
    /** 选中项值的key */
    labelKey: {
      default: "name",
      type: String
    },
    value: {
      required: false
    },
    /** 在返回选项时，是否将原始数据返回，默认只返回 value */
    metaInValue: {
      type: Boolean,
      default: false,
      required: false
    },
    /** 是否可以删除 */
    clearable: {
      type: Boolean,
      default: false
    },
    /** 是否可以多选 */
    multiple: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: "请选择"
    },
    /** 是否禁用 */
    disabled: {
      type: Boolean,
      default: false
    }
  },
  components: {
    Select,
    Option
  },
  model: {
    prop: "value",
    event: "on-change"
  },
  data: function() {
    return {
      Uuid: Uuid,
      options: [],
      loading: false
    };
  },
  computed: {
    initValue: function() {
      let value = this.$props.value;
      value = this.initMetaValue(value);
      return value;
    }
  },
  watch: {
    api: function(newValue, oldValue) {
      if (!compare(newValue, oldValue)) {
        this.loadData();
      }
    },
    queryParam: function(newValue, oldValue) {
      if (!compare(newValue, oldValue)) {
        this.loadData();
      }
    }
  },
  async beforeMount() {
    let value = this.value;
    this.loadData();
  },
  methods: {
    async loadData() {
      if (this.$props.api) {
        if (this.needQueryParam && !this.queryParam) {
          return;
        }
        this.loading = true;
        if (this.namespace) {
          this.$store.commit(`${namespace}/saveState`, { loading: true });
        }
        let responst = await appService.getRequest(
          this.$props.api,
          this.$props.queryParam
        );
        this.loading = false;
        if (this.namespace) {
          this.$store.commit(`${namespace}/saveState`, { loading: false });
        }
        if (responst.status === 200 && responst.data.errorCode === 0) {
          let options = responst.data.data;
          options = this.initMetaData(options);
          this.options = options;
        }
      }
    },
    /** 初始化默认数据，并返回初始化后的默认数据 */
    initMetaValue(metaValue) {
      let result = [];
      if (metaValue instanceof Array) {
        for (let i = 0; i < metaValue.length; i++) {
          if (metaValue[i] instanceof Object) {
            result.push(metaValue[i][this.valueKey]);
          } else {
            result.push(metaValue[i]);
          }
        }
      } else {
        if (metaValue instanceof Object) {
          result.push(metaValue[this.valueKey]);
        } else {
          result.push(metaValue);
        }
      }
      return result;
    },
    /** 初始化原始数据，并返回初始化后的数据 */
    initMetaData(metaData) {
      if (!metaData) {
        metaData = [];
      } else {
        if (metaData instanceof Function) {
          metaData = [];
        } else if (!(metaData instanceof Array)) {
          metaData = [metaData];
        }
      }
      let labelKey = this.labelKey;
      let valueKey = this.valueKey;
      let options = [];
      for (let i = 0; i < metaData.length; i++) {
        let option = {
          metaData: metaData[i]
        };
        option[labelKey] = metaData[i][labelKey];
        option[valueKey] = metaData[i][valueKey];
        options.push(option);
      }
      return options;
    },
    handleChange(selectedOptions) {
      if (!selectedOptions) {
        this.$emit("on-change");
      }
      let options = this.options;
      if (selectedOptions instanceof Array) {
        if (this.$props.metaInValue) {
          let metaDatas = [];
          for (let i = 0; i < selectedOptions.length; i++) {
            for (let h = 0; h < options.length; h++) {
              if (options[h][this.valueKey] === selectedOptions[i]) {
                metaDatas.push(options[h].metaData);
                break;
              }
            }
          }
          this.$emit("on-change", metaDatas);
          return;
        } else {
          this.$emit("on-change", selectedOptions);
        }
      } else {
        if (this.$props.metaInValue) {
          for (let i = 0; i < options.length; i++) {
            if (options[i][this.$props.valueKey] === selectedOptions) {
              let metaData = options[i].metaData;
              this.$emit("on-change", metaData);
              return;
            }
          }
        } else {
          this.$emit("on-change", selectedOptions);
        }
      }
    }
  }
};
</script>
